package form

import (
	"fmt"
	"reflect"
	"strings"
	"time"

	"go.mongodb.org/mongo-driver/bson/primitive"
)

// Builder 表单构建器接口
type Builder interface {
	Build() primitive.M
	// Set 设置字段值
	Set(field string, value interface{}) Builder
	// SetIfNotEmpty 当值不为空时设置字段
	SetIfNotEmpty(field string, value interface{}) Builder
	// SetIfNotZero 当值不为零值时设置字段
	SetIfNotZero(field string, value interface{}) Builder
	// FromModel 新增方法
	FromModel(model interface{}) Builder
	// SetMap 批量设置字段值
	SetMap(fields map[string]interface{}) Builder
	// GetError 获取处理过程中的错误
	GetError() error
}

type builder struct {
	doc primitive.M
	err error
}

func NewBuilder() Builder {
	return &builder{
		doc: primitive.M{},
	}
}

// Build 构建最终的 BSON 文档
func (b *builder) Build() primitive.M {
	return b.doc
}

// Set 设置字段值
func (b *builder) Set(field string, value interface{}) Builder {
	b.doc[field] = value
	return b
}

// SetIfNotEmpty 当值不为空时设置字段
func (b *builder) SetIfNotEmpty(field string, value interface{}) Builder {
	if value != nil && value != "" {
		b.doc[field] = value
	}
	return b
}

// SetIfNotZero 当值不为零值时设置字段
func (b *builder) SetIfNotZero(field string, value interface{}) Builder {
	if !isZero(value) {
		b.doc[field] = value
	}
	return b
}

// isZero 检查值是否为零值
func isZero(value interface{}) bool {
	if value == nil {
		return true
	}

	switch v := value.(type) {
	case int, int8, int16, int32, int64:
		return reflect.ValueOf(v).Int() == 0
	case uint, uint8, uint16, uint32, uint64:
		return reflect.ValueOf(v).Uint() == 0
	case float32, float64:
		return reflect.ValueOf(v).Float() == 0
	case string:
		return v == ""
	case bool:
		return !v
	case time.Time:
		return v.IsZero()
	case []interface{}, []string, []int:
		return reflect.ValueOf(v).Len() == 0
	case primitive.ObjectID:
		return v.IsZero()
	default:
		// 处理指针类型
		rv := reflect.ValueOf(v)
		if rv.Kind() == reflect.Ptr {
			return rv.IsNil()
		}
		// 处理结构体类型
		if rv.Kind() == reflect.Struct {
			// 检查结构体的所有字段是否都为零值
			for i := 0; i < rv.NumField(); i++ {
				if !isZero(rv.Field(i).Interface()) {
					return false
				}
			}
			return true
		}
		// 处理切片类型
		if rv.Kind() == reflect.Slice || rv.Kind() == reflect.Array {
			return rv.Len() == 0
		}
		// 其他类型使用反射判断
		return rv.IsZero()
	}
}

// FromModel 从模型构建文档
func (b *builder) FromModel(model interface{}) Builder {
	if model == nil {
		return b
	}

	val := reflect.ValueOf(model)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}

	if val.Kind() != reflect.Struct {
		b.err = fmt.Errorf("model must be a struct or pointer to struct")
		return b
	}

	typ := val.Type()
	for i := 0; i < val.NumField(); i++ {
		field := typ.Field(i)
		value := val.Field(i)

		bsonTag := field.Tag.Get("bson")
		if bsonTag == "" || bsonTag == "-" {
			continue
		}

		// 获取 bson 标签中的第一部分（去掉 omitempty 等选项）
		tagParts := strings.Split(bsonTag, ",")
		fieldName := tagParts[0]

		// 处理数组/切片类型
		if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
			if !isZero(value.Interface()) {
				b.Set(fieldName, value.Interface())
			}
			continue
		}

		// 处理嵌套结构体
		if value.Kind() == reflect.Struct {
			// 特殊处理时间类型
			if _, ok := value.Interface().(time.Time); ok {
				b.SetIfNotZero(fieldName, value.Interface())
				continue
			}
			// 递归处理嵌套结构体
			nested := NewBuilder().FromModel(value.Interface()).Build()
			if len(nested) > 0 {
				b.Set(fieldName, nested)
			}
			continue
		}

		// 处理指针类型
		if value.Kind() == reflect.Ptr && !value.IsNil() {
			b.SetIfNotZero(fieldName, value.Elem().Interface())
			continue
		}

		// 处理普通字段
		b.SetIfNotZero(fieldName, value.Interface())
	}

	return b
}

// SetMap 批量设置字段值
func (b *builder) SetMap(fields map[string]interface{}) Builder {
	for field, value := range fields {
		b.Set(field, value)
	}
	return b
}

func (b *builder) GetError() error {
	return b.err
}

/**

// 示例模型
type User struct {
    ID        primitive.ObjectID `bson:"_id,omitempty"`
    Name      string            `bson:"name"`
    Email     string            `bson:"email,omitempty"`
    Age       int               `bson:"age,omitempty"`
    CreatedAt time.Time         `bson:"created_at"`
    UpdatedAt *time.Time        `bson:"updated_at,omitempty"`
    Profile   struct {
        Avatar string `bson:"avatar"`
        Bio    string `bson:"bio,omitempty"`
    } `bson:"profile"`
}

// 使用示例
func Example() {
    user := &User{
        Name: "张三",
        Age:  25,
        Profile: struct {
            Avatar string `bson:"avatar"`
            Bio    string `bson:"bio,omitempty"`
        }{
            Avatar: "avatar.jpg",
            Bio:    "这是简介",
        },
    }

    // 方式1：直接从模型构建
    doc1 := NewBuilder().FromModel(user).Build()

    // 方式2：混合使用
    doc2 := NewBuilder().
        FromModel(user).
        Set("extra_field", "���外字段").
        SetIfNotEmpty("optional_field", optionalValue).
        Build()
}
**/
